﻿using System;

//
using System.Collections;
using System.Collections.Generic;


namespace DailyFx.IndicatorExtension
{

    public class SMD : Index
    {
		/// <summary>
		///		Sampling window size .
		/// </summary>
		private int _span = 14;


        public SMD ( int span, int n) : base ( 2, n )
        {
			this.variance = new HyperVector ( n, "VAR", Layout.HYBRID, Stylus.HIDDEN, 0 );
			this.deviation = new HyperVector ( n, "DEV", Layout.HYBRID, Stylus.HIDDEN, 1 );

            //
            if ( span <= 0 )
                this._span = 14;
        }



        public override void Cook ( BarSeries series )
        {

            decimal sum = 0.0m;
            decimal ma = 0.0m;

            decimal V = 0.0m;
            decimal v = 0.0m;
            decimal diff = 0.0m;

            decimal p = 0.0m;

            for (int n = 0; n < Length; n++)
            {
                //
                //
				decimal x = series[n].LastPx;

				sum += series[n].LastPx;
                sum -= p;

                // HAHA, i figure out a quick way ...

                if (n < this._span) // still preparing 
                {
                    ma = sum / (n + 1);

                    if (n > 0)
                    {
                        diff = ((n + 1) * x) - sum;
                        V += (diff * diff) / (n * (n - 1));
                        v = V / n;
                    }
                }
                else              // forming 
                {
					ma = sum / this._span;

					V += (x * x) - (p * p) + (x - p - 2 * sum) / this._span;
					v = V / (this._span - 1);

					p = series [n - this._span].LastPx;
                }

                this.variance[n] = v ;
                this.deviation[n] = Math2.Sqrt( v);
            }
        }

        public virtual void Cook2 ( IVector target )
        {
			/**
            if ( u.mRaws != this.mRaws )
                throw new ArgumentException ("");
			*/


			decimal sum = 0.0m;
            decimal ma = 0.0m;

            decimal V = 0.0m;
            decimal v = 0.0m;
            decimal diff = 0.0m;

            decimal p = 0.0m;

            for (int n = 0; n < target.Length; n++)
            {
                //
                //
                decimal x = target[n];

                sum += target[n];
                sum -= p;


                if (n < this._span ) // still preparing 
                {
                    ma = sum / (n + 1);

                    if (n > 0)
                    {
                        diff = ((n + 1) * x) - sum;
                        V += (diff * diff) / (n * (n - 1));
                        v = V / n;
                    }
                }
                else              // forming 
                {
                    ma = sum / this._span;

					V += (x * x) - (p * p) + (x - p - 2 * sum) / this.Period;
					v = V / (this.Period - 1);

					p = target[n - this._span];
                }

                this.variance[n] = v ;
                this.deviation[n] = Math2.Sqrt( v);
            }
        }



        public override string Family
        {
            get { return "Standard Variance & Deviation"; }
        }

        public override string Label
        {
            get { return "SMD"; }
        }


       

		public HyperVector variance
		{
			get {
				return _children[0];
			}
			private set {
				_children[0] = value;
			}
		}

		public HyperVector deviation
		{
			get {
				return _children[1];
			}
			private set {
				_children[1] = value;
			}
		}

		//
		public Int32 Period
		{
			get { return _span; }
			set { _span = value; }
		}

    }


}
